package com.witsight.hibernate.dao;

import java.io.Serializable;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.hibernate.SessionFactory;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.query.spi.NamedQueryRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.util.Assert;

import com.witsight.hibernate.dao.impl.DynamicSimpleJpaRepository;
import com.witsight.platform.dao.CommonRepository;

/**   
 * 说明：构建自己的工厂类，创建出对应的Dao实现
 * @Title: CustomJpaRepositoryFactory.java 
 * @Package com.witsight.hibernate.dao 
 * @See: {@link JpaRepositoryFactory}
 * Copyright: Copyright (c) 2017
 * Company:sany huax witsight team by product
 * @author: fuyp  
 * @date: 2017年9月14日 下午2:31:16 
 * @version: V1.0
 *
 */
public class CustomJpaRepositoryFactory extends JpaRepositoryFactory {
	/**
     * Logger
     */
    private static final Logger log = LoggerFactory.getLogger(CustomJpaRepositoryFactory.class);
    
    private EntityManagerFactory entityManagerFactory;
	private CommonRepository commonRepository;
	public CustomJpaRepositoryFactory(EntityManager entityManager,EntityManagerFactory sessionFactory,CommonRepository commonRepository) {
		super(entityManager);
		this.entityManagerFactory = sessionFactory;
		Assert.notNull(commonRepository, "commonRepository is null");
		this.commonRepository = commonRepository;
	}
	
	/**
	 * 取得对应的Dao的实现类的Class
	 * (non-Javadoc)  
	 * @Title: getRepositoryBaseClass
	 * @See: 取得对应的Dao的实现类的Class
	 * @author fuyp 
	 * @param metadata Dao信息
	 * @return Dao的实现类的Class
	 * @date: 2015年4月22日 下午12:20:53
	 */
	@Override
	protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
		if (isCustomDynamicQuery(metadata.getRepositoryInterface())) {
			return DynamicSimpleJpaRepository.class;
		}

		return super.getRepositoryBaseClass(metadata);
	}
	
	/**
	 * 取得对应的Dao的实现类的对象
	 * (non-Javadoc)  
	 * @Title: getTargetRepository
	 * @See: 取得对应的Dao的实现类的对象
	 * @author fuyp 
	 * @param metadata Dao信息
	 * @param entityManager 实体管理器
	 * @return Dao的实现类的对象
	 * @date: 2015年4月22日 下午12:21:17
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	protected <T, ID extends Serializable> SimpleJpaRepository<?, ?> getTargetRepository(
			RepositoryInformation metadata, EntityManager entityManager) {
		Class<?> repositoryInterface = metadata.getRepositoryInterface();
		JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
		SimpleJpaRepository<?, ?> repo = null;
		
		if (isCustomDynamicQuery(repositoryInterface)) {
			if (log.isDebugEnabled()) {
				log.info("{}'s class be instanced DynamicSimpleJpaRepository." , repositoryInterface);
			}
			NamedQueryRepository namedQueryRepository = null;
			Object sessionFactory = entityManagerFactory.createEntityManager().getEntityManagerFactory();
			if (sessionFactory instanceof SessionFactoryImpl) {
				namedQueryRepository = ((SessionFactoryImpl) sessionFactory).getNamedQueryRepository();
			}
			repo = new DynamicSimpleJpaRepository(entityInformation, entityManager, namedQueryRepository, commonRepository);
			return repo;
		}
		
		return super.getTargetRepository(metadata, entityManager);
	}
	/**
	 * 
	 * 说明：判断是否需要动态sql语句
	 * @Title: isCustomDynamicQuery
	 * @See: 判断是否需要动态sql语句
	 * @author fuyp 
	 * @param repositoryInterface 接口
	 * @return  true ： 正确  false：不正确
	 * @date: 2015年4月22日 下午12:21:56
	 */
	private boolean isCustomDynamicQuery(Class<?> repositoryInterface) {
		return BaseJpaRepository.class.isAssignableFrom(repositoryInterface);
	}
}
